#ifndef _VULKAN_PIPELINE_H_
#define _VULKAN_PIPELINE_H_

namespace Vulkan {
	namespace Pipeline {
		VkPipelineShaderStageCreateInfo shaderStageCreateInfo(const std::string& path, const VkShaderStageFlagBits flag) {
			auto module = createShaderModule(path);
			VkPipelineShaderStageCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
			info.stage = flag;
			info.module = module;
			info.pName = "main";
			return info;
		}

		VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
			std::vector<VkVertexInputBindingDescription>& bindings,
			std::vector<VkVertexInputAttributeDescription>& attributes) {
			VkPipelineVertexInputStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
			info.vertexBindingDescriptionCount = (uint32_t)bindings.size();
			info.pVertexBindingDescriptions = bindings.data();
			info.vertexAttributeDescriptionCount = (uint32_t)attributes.size();
			info.pVertexAttributeDescriptions = attributes.data();
			return info;
		}

		VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(
			VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
			VkBool32 primitiveRestartEnable = VK_FALSE)
		{
			VkPipelineInputAssemblyStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
			info.topology = topology;
			info.primitiveRestartEnable = primitiveRestartEnable;
			return info;
		}

		VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo(
			VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL,
			VkCullModeFlags cullMode = VK_CULL_MODE_NONE,
			VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE)
		{
			VkPipelineRasterizationStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
			info.polygonMode = polygonMode;
			info.cullMode = cullMode;
			info.frontFace = frontFace;
			info.depthClampEnable = VK_FALSE;
			info.rasterizerDiscardEnable = VK_FALSE;
			info.depthBiasClamp = VK_FALSE;
			info.lineWidth = 1.0f;
			return info;
		}

		VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo(
			uint32_t attachmentCount,
			const VkPipelineColorBlendAttachmentState * pAttachments)
		{
			VkPipelineColorBlendStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
			info.attachmentCount = attachmentCount;
			info.pAttachments = pAttachments;
			return info;
		}

		VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo(
			VkBool32 depthTestEnable = VK_TRUE,
			VkBool32 depthWriteEnable = VK_TRUE,
			VkCompareOp depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL)
		{
			VkPipelineDepthStencilStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
			info.depthTestEnable = depthTestEnable;
			info.depthWriteEnable = depthWriteEnable;
			info.depthCompareOp = depthCompareOp;
			info.front = info.back;
			info.back.compareOp = VK_COMPARE_OP_ALWAYS;
			return info;
		}

		VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo()
		{
			VkPipelineMultisampleStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
			info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
			info.sampleShadingEnable = VK_FALSE;
			info.minSampleShading = 1.0f; // Optional
			info.pSampleMask = nullptr; /// Optional
			info.alphaToCoverageEnable = VK_FALSE; // Optional
			info.alphaToOneEnable = VK_FALSE; // Optional
			return info;
		}

		VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(
			uint32_t viewportCount = 1,const VkViewport* pViewports = nullptr,
			uint32_t scissorCount = 1,const VkRect2D* pScissors = nullptr)
		{
			VkPipelineViewportStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
			info.viewportCount = viewportCount;
			info.pViewports = pViewports;
			info.scissorCount = scissorCount;
			info.pScissors = pScissors;
			return info;
		}

		VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(
			uint32_t count,const VkDynamicState* dynamic)
		{
			VkPipelineDynamicStateCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
			info.pDynamicStates = dynamic;
			info.dynamicStateCount = count;
			return info;
		}

		VkGraphicsPipelineCreateInfo pipelineCreateInfo(const VkRenderPass& pass, const VkPipelineLayout& layout) {
			VkGraphicsPipelineCreateInfo info = {};
			info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
			info.layout = layout;
			info.renderPass = pass;
			info.basePipelineIndex = -1;
			return info;
		}

		VkDescriptorSetLayout createBaseSetLayout() {
			std::vector<VkDescriptorSetLayoutBinding> bindings = {
				{0,VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,1,VK_SHADER_STAGE_VERTEX_BIT,nullptr},
				{1,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,1,VK_SHADER_STAGE_FRAGMENT_BIT,nullptr}
			};
			return createSetLayout(bindings);
		}
	}
}

#endif
